package db

import (
	"asocrawler/conf"
	"asocrawler/tool"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"
)

var db *sql.DB
var overSeasDb *sql.DB

func init() {
	var err error
	db, err = sql.Open("mysql", conf.Conf.MySqlDb)
	if err != nil {
		panic(err)
	}
	if err = db.Ping(); err != nil {
		panic(err.Error())
	}

	db.SetConnMaxLifetime(4 * time.Hour)

	// 海外数据库
	overSeasDb, err = sql.Open("mysql", conf.Conf.OverseasMySqlDb)
	if err != nil {
		panic(err)
	}
	if err = overSeasDb.Ping(); err != nil {
		panic(err.Error())
	}

	overSeasDb.SetConnMaxLifetime(4 * time.Hour)

}

//保存数据  ApiData 数据  channelName 渠道名 vType 榜单类别  date 日期
func SaveData(d DbDataResult) (err error) {
	tx, err := db.Begin()
	if err != nil {
		return
	}
	defer tx.Commit()
	//首先 删除该渠道 该榜单类别(ios 还包括classify) 该天的旧数据
	_, err = tx.Exec("delete from rankdata where channelName = ? and rankType = ? and `date` = ? and `classify` = ?", d.ChannelName, d.RankType, d.Date, d.Classify)
	if err != nil {
		tx.Rollback()
		return
	}

	//加入新数据
	for _, v := range d.Data {
		_, err = tx.Exec("insert into rankdata(appId,gameDesc,gameName,gameVersion,onSaleDate,playCount,typeName,rankType,dIndex,`date`,channelName,platform,bRank,downloadNum,score,company,classify,totalDownloadCount,commentCount,originalUrl) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
			v.AppId,
			v.GameDesc,
			v.GameName,
			v.GameVersion,
			v.OnSaleDate,
			v.PlayCount,
			v.TypeName,
			d.RankType,
			v.DIndex,
			d.Date,
			d.ChannelName,
			d.Platform,
			v.BRank,
			v.DownloadNum,
			v.Score,
			v.Company,
			v.Classify,
			v.TotalDownloadCount,
			v.CommentCount,
			v.OriginalUrl,
		)
		if err != nil {
			tx.Rollback()
			return
		}
		//除七麦平台，其他数据直接使用原icon 存入icon表中
		if v.Icon != "" {
			err = SaveIcon(v.AppId, v.Icon, d.ChannelName, d.Platform)
			if err != nil {
				log.Println("存入icon表中失败", v.AppId, v.Icon)
				continue
			}
		}
	}

	err = tool.SyncToCdn()
	if err != nil {
		return
	}

	return
}

func SaveIcon(appId, iconUrl, channelName, platform string) (err error) {
	_, err = db.Exec("insert ignore icon(appId,icon,channelName,platform) values (?,?,?,?)", appId, iconUrl, channelName, platform)
	if err != nil {
		log.Println("存入icon表中失败", appId, iconUrl)
		return
	}
	return
}

//从七麦获取图片
func GetAppIcon(iconUrl, appId, channelName, platform string) (err error) {
	notImg := strings.Contains(iconUrl, "static-cdn.qimai.cn")
	if !notImg {
		//如果图片可以直接用，则不用下载图片，直接存入icon表中
		err = SaveIcon(appId, iconUrl, channelName, platform)
		if err != nil {
			return
		}
		return
	}
	client := &http.Client{}
	req, err := http.NewRequest("GET", iconUrl, nil)
	if err != nil {
		return
	}
	req.Header.Set("referer", "https://www.qimai.cn/rank/marketRank")

	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()

	contentType := resp.Header.Get("content-type")
	fileType := strings.Split(contentType, "/")[1]

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	//下载图片后，生成新的cdn-url
	filePath, err := tool.SaveFile(b, fileType, appId)
	if err != nil {
		return
	}
	//cdn-url 存入icon表中
	err = SaveIcon(appId, filePath, channelName, platform)
	if err != nil {
		return
	}
	return
}

func GetAppIconMap(channelName, platform string) (appIconMap map[string]int, err error) {
	appIconMap = make(map[string]int)
	rows, err := db.Query("select appId from icon where channelName = ? and platform = ?", channelName, platform)
	if err != nil {
		return
	}
	defer rows.Close()
	for rows.Next() {
		var appId string
		err = rows.Scan(&appId)
		if err != nil {
			return
		}
		appIconMap[appId] = 1
	}
	return
}

// 存入数据库
func SaveTopicRank(ts []TopicRank, selectDate string) (err error) {
	tx, err := db.Begin()
	if err != nil {
		return
	}
	defer tx.Commit()
	for _, t := range ts {
		_, err = tx.Exec(`replace into challengerank(dateDay, periodType, challengeId, challengeName, coverImageUri, isOfficial, publishCount,publishAllCount, hot,allHot, LikeCount,allLikeCount)
 				values(?,?,?,?,?,?,?,?,?,?,?,?)`,
			t.DateDay,
			t.PeriodType,
			t.ChallengeId,
			t.ChallengeName,
			t.CoverImageUri,
			t.IsOfficial,
			t.PublishCount,
			t.PublishAllCount,
			t.Hot,
			t.AllHot,
			t.LikeCount,
			t.AllLikeCount)
		if err != nil {
			tx.Rollback()
			return
		}
	}

	//记录第一次存入的时间
	_, err = tx.Exec("insert ignore challengeIdTime (challengeId,createTime) select challengeId,dateDay from challengerank where dateDay = ? group by challengeId", selectDate)
	if err != nil {
		tx.Rollback()
		return
	}

	return
}

// 同步香港服务器 数据
func SyncHkGoogleData(channelName, platform, classify, date string) (err error) {
	tx, err := db.Begin()
	if err != nil {
		log.Println("SyncHkGoogleData error1,err=", err)
		return
	}
	defer tx.Commit()

	// -----同步rankdata--------

	// 首先 删除 该天的旧数据
	_, err = tx.Exec("delete from rankdata where channelName = ? and platform = ? and `date` = ? and `classify` = ?", channelName, platform, date, classify)
	if err != nil {
		log.Println("SyncHkGoogleData error1.1,err=", err)
		tx.Rollback()
		return
	}

	// 同步新数据
	rows, err := overSeasDb.Query(
		`select appId,gameDesc,gameName,gameVersion,icon,onSaleDate,playCount,typeName,
       rankType,dIndex,date,channelName,platform,bRank,collectTime,downloadNum,score,company,classify,totalDownloadCount,commentCount,originalUrl 
from rankdata where channelName = ? and platform = ? and date = ?`,
		channelName, platform, date)
	if err != nil {
		log.Println("SyncHkGoogleData error2,err=", err)
		tx.Rollback()
		return
	}

	for rows.Next() {
		var a ApiData
		err = rows.Scan(&a.AppId, &a.GameDesc, &a.GameName, &a.GameVersion, &a.Icon, &a.OnSaleDate, &a.PlayCount, &a.TypeName, &a.RankType, &a.DIndex,
			&a.Date, &a.ChannelName, &a.Platform, &a.BRank, &a.CollectTime, &a.DownloadNum, &a.Score, &a.Company, &a.Classify, &a.TotalDownloadCount,
			&a.CommentCount, &a.OriginalUrl,
		)
		if err != nil {
			log.Println("SyncHkGoogleData error3,err=", err)
			tx.Rollback()
			return
		}
		_, err = tx.Exec("insert into rankdata(appId,gameDesc,gameName,gameVersion,onSaleDate,playCount,typeName,rankType,dIndex,`date`,channelName,platform,bRank,collectTime,downloadNum,score,company,classify,totalDownloadCount,commentCount,originalUrl ) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
			a.AppId,
			a.GameDesc,
			a.GameName,
			a.GameVersion,
			a.OnSaleDate,
			a.PlayCount,
			a.TypeName,
			a.RankType,
			a.DIndex,
			a.Date,
			a.ChannelName,
			a.Platform,
			a.BRank,
			a.CollectTime,
			a.DownloadNum,
			a.Score,
			a.Company,
			a.Classify,
			a.TotalDownloadCount,
			a.CommentCount,
			a.OriginalUrl,
		)
		if err != nil {
			log.Println("SyncHkGoogleData error3.1,err=", err)
			tx.Rollback()
			return
		}
	}

	// ------同步icon---------
	rows2, err := overSeasDb.Query(`select appId,icon,channelName,platform,collectTime
		from icon where channelName = ? and platform = ? and collectTime >  ?`,
		channelName, platform, date)
	if err != nil {
		log.Println("SyncHkGoogleData error4,err=", err)
		tx.Rollback()
		return
	}

	for rows2.Next() {
		var i Icon
		err = rows2.Scan(&i.AppId, &i.Icon, &i.ChannelName, &i.Platform, &i.CollectTime)
		if err != nil {
			log.Println("SyncHkGoogleData error5,err=", err)
			tx.Rollback()
			return
		}
		_, err = db.Exec("insert ignore icon(appId,icon,channelName,platform,collectTime) values (?,?,?,?,?)", i.AppId, i.Icon, i.ChannelName, i.Platform, i.CollectTime)
		if err != nil {
			log.Println("SyncHkGoogleData error6,err=", err)
			tx.Rollback()
			return
		}
	}

	return
}
